// Header Protection
#ifndef _LISTENER_H_
#define _LISTENER_H_

// Include Files
#include "Definitions.h"
#include "Event.h"
#include "Notification.h"

// Namespace
namespace IE
{
	/////////////////////////////////////////////////////////////////////////////////
	// Classes derive from IListener to gain the ability to listen for events.
	class IListener
	{
	protected:  // child methods
		IListener() : m_NotificationMutex(), m_lstpNotifications() { }
		virtual ~IListener() { }

		// Register this listener for the event with the given event handler.
		// listener_t : template - the type of the derived listener class
		// eventarg_t : template - the type of the event argument
		// _rEvent : CEvent<eventarg_t> & - the event to listen for
		// _pHandler : void (listener_t::*)(eventarg_t &) - the event handler to 
		//     call when the event is raised
		template< class listener_t, class eventarg_t >
		inline void AddEventListener( 
			CEvent<eventarg_t> &_rEvent, void (listener_t::*_pHandler)(eventarg_t &) )
		{
			// add the registration to the event
			_rEvent.AddRegistration( (listener_t*)this, _pHandler);
		}

		// Unregister this listener from the event with the given event handler.
		// listener_t : template - the type of the derived listener class
		// eventarg_t : template - the type of the event argument
		// _rEvent : CEvent<eventarg_t> & - the event to stop listening for
		// _pHandler : void (listener_t::*)(eventarg_t &) - the event handler which 
		//     was used to listen for the event.
		template< class listener_t, class eventarg_t >
		inline void RemoveEventListener( 
			CEvent< eventarg_t > &_rEvent, void (listener_t::*_pHandler)(eventarg_t &) )
		{
			// remove the registration from the event
			_rEvent.RemoveRegistration( (listener_t*)this, _pHandler );
		}

		// Call the event handlers for each event which has been raised since the 
		//     last time this method was called. If this method is never called, 
		//     event handlers will never be called.
		void ProcessEvents();

	private:    // ABCRegistration friend methods
		friend class ABCRegistration;

		// An event which this listener is registered for has been raised. Add a 
		//     notification to the queue to be processed.
		// _pNot : ABCNotification * - the notification to add to the queue
		inline void Raise( ABCNotification *_pNot )
		{
			// append the notification to the list
			m_NotificationMutex.Lock();
			m_lstpNotifications.Append(_pNot);
			m_NotificationMutex.Unlock();
		}

	private:    // data
		mutex_t                    m_NotificationMutex;
		flist_t<ABCNotification *> m_lstpNotifications;

	private:    // dummy definitions
		IListener( IListener const & );
		IListener &operator =( IListener const & );
	};
}

// Header Protection
#endif // _LISTENER_H_
